package com.pubinfo.passbook.engine.chain.transfer;

import com.pubinfo.passbook.common.model.dto.witeoff.MedicineOnJobOrRetireDTO;
import com.pubinfo.passbook.common.model.ruler.PayInformation;
import com.pubinfo.passbook.common.service.ruler.InformationService;
import com.pubinfo.passbook.engine.utils.ApplicationContextUilts;
import com.pubinfo.passbook.engine.chain.ComputeChain;
import com.pubinfo.passbook.engine.constants.ComputeChainType;
import com.pubinfo.passbook.engine.constants.ComputeResultType;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 医疗费子单计算链到医疗费计算单元转换
 * <p>
 * 医药费循环链很特别. 每次进入循环链需要重置链子中的初始值为0, 执行完成后累加
 *
 * @author zhouch
 * @date 2021/12/13 16:55
 */
public class MedicineToSubTransfer extends ComputeLoopChainTransfer<MedicineOnJobOrRetireDTO, PayInformation, BigDecimal> {

    private final InformationService informationService;

    public MedicineToSubTransfer(ComputeChain<PayInformation, BigDecimal> computor) {
        super(computor);
        informationService = ApplicationContextUilts.getBean(InformationService.class);
    }

    /**
     * 循环计算链执行
     *
     * @param data
     * @param beforeVal
     * @return
     */
    @Override
    public BigDecimal compute(MedicineOnJobOrRetireDTO data, BigDecimal beforeVal) {
        AtomicReference<BigDecimal> result = new AtomicReference<>(beforeVal);
        realComputeChain.setCache(cache);
        for (PayInformation subData : convertToCollection(data)) {
            // 局部归零
            AtomicReference<BigDecimal> localResult = new AtomicReference<>(new BigDecimal(0));
            localResult.set(realComputeChain.compute(subData, localResult.get()));

            // 执行完后累加局部结果
            result.set(result.get().add(localResult.get()));
        }
        return result.get();
    }

    /**
     * 返回转化目标计算链类型
     *
     * @return
     */
    @Override
    public String getChainType() {
        return ComputeChainType.MEDICINE;
    }

    @Override
    public String getResultType() {
        return ComputeResultType.NUMBER;
    }


    @Override
    Collection<PayInformation> convertToCollection(MedicineOnJobOrRetireDTO data) {
        return informationService.listInformationFromPassbook(data.getInvoiceIds());
    }
}
